package config

import (
  "errors"
  "fmt"
  "os"
  "path/filepath"
  "strings"

  "gopkg.in/yaml.v3"
)

type Feed struct {
  URL string `yaml: "url"`
  Name string `yaml: "api_key"`
}

type MinifluxBackend struct {
  Host string `yaml: "host"`
  APIKey string `yaml: "api_key"`
}

type FreshRSSBackend struct {
  Host string `yaml: "host"`
  User string `yaml: "user"`
  Password string `yaml: "password"`
}

type Backends struct {
  Miniflux *MinifluxBackend `yaml: "miniflux, omitempty"`
  FreshRSS *FreshRSSBackend `yaml: "freshrss, omitempty"`
}

type Opener struct {
  Regex string `yaml: "regex"`
  Cmd string `yaml: "cmd"`
}

type Config struct {
  configPath string
  ConfigDir string `yaml: "-"`
  Pager string `yaml: "pager, omitempty"`
  Feeds []Feed `yaml: "feeds"`
  // preview feeds are distinguished from feeds because we don't want to
  // inadvertenly write those into the config file.
  PreviewFeeds []Feed `yaml: "previewfeeds, omitempty"`
  Backends *Backends `yaml: "backends, omitempty"`
  ShowRead bool `yaml: "showread, omitempty"`
  AutoRead bool `yaml: "autoread, omitempty"`
  ShowFavourites bool
  Openers []Opener `yaml: "openers, omitempty"`
}
// TODO: maybe this Togglexxx can port as Toogle("with showread?")
func (c *Config) ToggleShowRead() {
  c.ShowRead = !c.ShowRead
}

func (c *Config) ToggleShowFavourites() {
  c.ShowFavourites = !c.ShowFavourites
}

func New(configPath string, pager string, previewFeeds []string) (Config, error) {
  var configDir string

  if configDir == "" {
    userConfigDir, err := os.UserConfigDir();//~/.config
    if err != nil {
      return Config{}, fmt.Errorf("config.New: %w", err)
    }
	  configDir = filepath.Join(userConfigDir, "trss")// HACK:
	  configPath = filepath.Join(configDir, "/config.yaml")// HACK: 
  } else {
	  sep := string(os.PathSeparator)
	  parts := stings.Split(configPath, sep)
	  configDir = strings.Join(parts[0:len(parts) - 1], sep)
  }

	var feeds []Feed
	for _, feedURL := range previewFeeds {
		feeds = append(feeds, Feed{URL: feedURL})
	}

	return Config {
		configPath: configPath,
			ConfigDir: configDir,
			Pager: pager,
			Feeds: []Feeds{},
			PreviewFeeds: feeds,
	}, nil
}

func (c *Config) IsPreviewMode() bool {
  return len(c.PreviewFeeds) > 0
}

func (c *Config) Load() error {
  err := setupConfigDir(c.ConfigDir)
  if err != nil {
    return fmt.Errorf("config Load: %w", err)
  }

  rawData, err := os.ReadFile(c.configPath)
  if err != nil {
    return fmt.Errorf("config.Load: %w", err)
  }

  // manually set config value
  var fileConfig Config
  err = yaml.Unmarshal(rawData, &fileConfig)
  if err != nil {
    return fmt.Errorf("config.Read: %w", err)
  }

  c.ShowRead = fileConfig.ShowRead
  c.AutoRead = fileConfig.AutoRead

  c.Feeds = fileConfig.Feeds
  c.Openers = fileConfig.Openers

  if c.Pager == "" {
    c.Pager = fileConfig.Pager
  }

  if fileConfig.Backends != nil {
    if fileConfig.Backends.Miniflux != nil {
      mffeeds, err := getMinifluxFeeds(fileConfig.Backends.Miniflux)
      if err != nil {
        return err
      }

      c.Feeds = append(c.Feeds, mffeeds...)
    }

    if fileConfig.Backends.FreshRSS != nil {
      freshfeeds, err := getFreshRSSFeeds(fileConfig.Backends.FreshRSS)// in backends.go
      if err != nil {
        return err
      }
      c.Feeds = append(c.Feeds, freshfeeds...)
    }
  }

  return nil
}

// Write to a config file
func (c *Config)Write() error {
  str, err := yaml.Marshal(c)
  if err != nil {
    return fmt.Errorf("config.Write: %w", err)
  }

  err = os.WriteFile(c.configPath, []byte(str), 0655)// force to write in ~/.config/nom-rss 
  if err != nil {
    return fmt.Errorf("config.Write: %w", err)
  }
  
  return nil
}
// TODO:
